#include <stdio.h>
#include <string.h>

#include "STC32G.H"
#include "STC32G_GPIO.h"
#include "STC32G_UART.h"
#include "STC32G_NVIC.h"
#include "STC32G_Delay.h"
#include "STC32G_Switch.h"

#include "config.h"
#include "app_config.h"
#include "debug.h"
#include "app.h"
#include "app_common.h"

#include "drv_rtc.h"
#include "drv_jiffes.h"
#include "drv_network.h"


#if ((TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_NB)||(TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_4G))

static struct app_t* _this=NULL;

static void network_module_uart_init(void)
{
    GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义
    COMx_InitDefine		COMx_InitStructure;					//结构定义

    GPIO_InitStructure.Pin  = GPIO_Pin_2 | GPIO_Pin_3;		//指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
	GPIO_InitStructure.Mode = GPIO_PullUp;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(GPIO_P5, &GPIO_InitStructure);	//初始化

    COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;		//模式,   UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
	COMx_InitStructure.UART_BRT_Use   = BRT_Timer4;			//选择波特率发生器, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2, 所以不用选择)
	COMx_InitStructure.UART_BaudRate  = TCFG_NETWORK_AT_BAUDRATE;			//波特率,     110 ~ 115200
	COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLE
	UART_Configuration(UART4, &COMx_InitStructure);		//初始化串口2 USART1,USART2,USART3,USART4
	NVIC_UART4_Init(ENABLE,Priority_1);		//中断使能, ENABLE/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3

	UART4_SW(UART4_SW_P52_P53);		//UART4_SW_P52_P53

}

/**
 * @brief   网络模块初始化
 * @param   app参考@struct app_t*
 * @return  无
*/
void network_module_init(struct app_t* app)
{
    _this = app;

    app->network.at_ready = 0;      // 上电默认AT命令为准备好
    app->network.simcardin = 0;     // 上电默认SIM卡未插入
    app->network.atcmd.status = AT_STATUS_IDLE; // 上电默认禁止AT命令发送
    app->network.atcmd.size = AT_CMD_LIST_LEN;
    app->network.net_connecting = 1; // 1:上电指示正在网络连接

    memset(app->dev_uuid, 0, sizeof(app->dev_uuid));

    // TODO: 清空4G模块AT命令队列
    network_atcmd_list_clear(app);

    // TODO: 清空4G模块AT命令接收缓冲
    app->network.rxlen = 0;
    memset(app->network.rxbuf, 0, sizeof(app->network.rxbuf));

    // TODO: 清空4G模块AT命令发射缓冲
    app->network.txlen = 0;
    memset(app->network.txbuf, 0, sizeof(app->network.txbuf));


    // TODO: 网络模块AT指令收发串口初始化
    network_module_uart_init();

}

int network_atcmd_uart_send(uint8_t *str, int len)
{
	int i=0;
	if (len <= 0) {
		return  0;
	}
    
    for (i=0; i<len; i++)
    {
        TX4_write2buff(str[i]);
    }

	return i;
}

/**
 * @brief   MQTT上报数据payload生成
 * @param   app:参考@struct app_t*
 * @return  payload字符串长度
*/
int mqtt_payload_generate(struct app_t* app)
{
    app->network.payload_len = 0;
    memset(app->network.payload_buf, 0, sizeof(app->network.payload_buf));

    sprintf(app->network.payload_buf, "CH4:%.02f, ERR:%d", (float)0.125, (int)80);
    app->network.payload_len = strlen(app->network.payload_buf);
    return app->network.payload_len;
}

/**
 * @brief   发送AT命令，拼接发送AT命令字符串
 * @param   app:参考@struct app_t*
 * @reutrn  无
 */
void network_atcmd_send_process(struct app_t* app)
{
    uint8_t at_arg = 0;

    // TODO: 清空接收缓冲
    // app->network.rxlen = 0;
    // memset(app->network.rxbuf, 0, sizeof(app->network.rxbuf));

    at_arg = app->network.atcmd.list[app->network.atcmd.action_idx].arg;

    switch(app->network.atcmd.list[app->network.atcmd.action_idx].cmd_id)
    {
        case ATCMD_ID_UNKNOW:    // 无效命令
            app->network.atcmd.status = AT_STATUS_IDLE;
            return;
    // TODO: 4G CAT1模块相关命令==============================================================
#if TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_4G
        case ATCMD_ID_4G_CPIN:        // +CPIN: READY
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_CPIN);
            break;
        case ATCMD_ID_4G_CSQ:         // +CSQ: 22,99
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_CSQ);
            break;
    #ifdef ATCMD_STR_4G_CPSI
        case ATCMD_ID_4G_CPSI:        // +CPSI: LTE,Online,460-00,0x252C,220581203,5,EUTRAN-BAND39,38544,3,0,30,51,44,14
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_CPSI);
            break;
    #endif
        case ATCMD_ID_4G_CGREG:       // +CGREG: 0,1
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_CGREG);
            break;
        case ATCMD_ID_4G_SIMEI:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_SIMEI);
            break;
        case ATCMD_ID_4G_CICCID:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_CICCID);
            break;
    #ifdef ATCMD_STR_4G_CRESET
        case ATCMD_ID_4G_CRESET:       // 4G模块 复位
            app->network.at_ready = 0;
            app->network.simcardin = 0;
            app->network.reg_mode = 0;
            app->network.reg_stat = 0;           
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_CRESET);
            break;
    #endif
        case ATCMD_ID_4G_CPOF:         // 4G模块 关机
            log_d("ATCMD_ID_4G_CPOF\n");
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_CPOF);
            break;
        case ATCMD_ID_4G_CTZU_GET:     // 查询 Automatic time and time zone update 
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_CTZU_GET);
            break;
        case ATCMD_ID_4G_CTZU_SET:     // 设置 Automatic time and time zone update 
            sprintf(app->network.txbuf, ATCMD_STR_4G_CTZU_SET, (int)at_arg);
            break;
        case ATCMD_ID_4G_CCLK:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_CCLK);
            break;
    #ifdef ATCMD_STR_4G_CFUN
        case ATCMD_ID_4G_CFUNC:
            sprintf(app->network.txbuf, ATCMD_STR_4G_CFUN, at_arg);
            break;
    #endif
        case ATCMD_ID_4G_CMQTTSTART:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_CMQTTSTART);
            break;
        case ATCMD_ID_4G_CMQTTACCQ:
            sprintf(app->network.payload_buf, TCFG_MQTT_CLIENTID_STR, app->dev_uuid);
            // sprintf(app->network.txbuf, ATCMD_STR_4G_CMQTTACCQ, TCFG_MQTT_CLIENTID_STR);
            sprintf(app->network.txbuf, ATCMD_STR_4G_CMQTTACCQ, app->network.payload_buf);
            break;
        case ATCMD_ID_4G_CMQTTCFG_VER:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_CMQTTCFG_VER);
            break;
        case ATCMD_ID_4G_CMQTTCFG_ARG:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_4G_CMQTTCFG_ARG);
            break;
        case ATCMD_ID_4G_CMQTTCONNECT:
            sprintf(app->network.txbuf, ATCMD_STR_4G_CMQTTCONNECT, TCFG_MQTT_4G_HOST_STR, TCFG_MQTT_USERNAME_STR, TCFG_MQTT_PASSWORD_STR);
            break;
        case ATCMD_ID_4G_CMQTTSUB:
            sprintf(app->network.txbuf, ATCMD_STR_4G_CMQTTSUB, TCFG_MQTT_SUBTOPIC_STR, (int)TCFG_MQTT_SUB_QOS);
            break;
        case ATCMD_ID_4G_CMQTTPAYLOAD:
        {
            int _len = mqtt_payload_generate(app);
            sprintf(app->network.txbuf, ATCMD_STR_4G_CMQTTPAYLOAD, _len);
        }
            break;
        case ATCMD_ID_4G_CMQTTPUB:
            sprintf(app->network.txbuf, ATCMD_STR_4G_CMQTTPUB, TCFG_MQTT_PUBTOPIC_STR, (int)TCFG_MQTT_PUB_QOS);
            break;
#elif TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_NB
    // TODO: NB-Iot模块相关命令==============================================================
        case ATCMD_ID_NB_CIMI:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_NB_CIMI);
            break;
        case ATCMD_ID_NB_NCCID:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_NB_NCCID);
            break;
        case ATCMD_ID_NB_CGSN:
            sprintf(app->network.txbuf, ATCMD_STR_NB_CGSN, (int)at_arg);
            break;
    #ifdef ATCMD_STR_NB_CGATT
        case ATCMD_ID_NB_CGATT:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_NB_CGATT);
            break;
    #endif
    #ifdef ATCMD_STR_NB_FASTOFF
        case ATCMD_ID_NB_FASTOFF:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_NB_FASTOFF);
            break;
    #endif
    #ifdef ATCMD_STR_NB_CPSMS
        case ATCMD_ID_NB_CPSMS:
            sprintf(app->network.txbuf, ATCMD_STR_NB_CPSMS, (int)at_arg);
            break;
    #endif
    #ifdef ATCMD_STR_NB_CPSMS_GET
        case ATCMD_ID_NB_CPSMS_GET:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_NB_CPSMS_GET);
            break;
    #endif
    #ifdef ATCMD_STR_NB_CGMR
        case ATCMD_ID_NB_CGMR:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_NB_CGMR);
            break;
    #endif
        case ATCMD_ID_NB_CEREG:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_NB_CERGE);
            break;
        case ATCMD_ID_NB_CESQ:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_NB_CESQ);
            break;
        case ATCMD_ID_NB_CSQ:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_NB_CSQ);
            break;
        case ATCMD_ID_NB_CCLK:
            sprintf(app->network.txbuf, "%s", ATCMD_STR_NB_CCLK);
            break;
        case ATCMD_ID_NB_MQNEW:
            sprintf(app->network.txbuf, ATCMD_STR_NB_MQNEW, TCFG_MQTT_NB_HOST_STR, TCFG_MQTT_PORT_STR, (int)TCFG_MQTT_TIMEOUT_MS, (int)TCFG_MQTT_BUFFSIZE);
            break;
        case ATCMD_ID_NB_MQCON:
            sprintf(app->network.payload_buf, TCFG_MQTT_CLIENTID_STR, app->dev_uuid);
            // sprintf(app->network.txbuf, ATCMD_STR_NB_MQCON, TCFG_MQTT_CLIENTID_STR, 1000, "WILL", (int)TCFG_MQTT_CON_QOS, "3838", TCFG_MQTT_USERNAME_STR, TCFG_MQTT_PASSWORD_STR);
            sprintf(app->network.txbuf, ATCMD_STR_NB_MQCON, app->network.payload_buf, (int)TCFG_MQTT_KEEPALIVE_S, "WILL", (int)TCFG_MQTT_SUB_QOS, "3838", TCFG_MQTT_USERNAME_STR, TCFG_MQTT_PASSWORD_STR);
            // sprintf(app->network.txbuf, ATCMD_STR_NB_MQCON, app->network.payload_buf, (int)TCFG_MQTT_KEEPALIVE_S, "WILL", (int)TCFG_MQTT_SUB_QOS, "3838", TCFG_MQTT_USERNAME_STR, app->private_data.mqtt_password);            
            break;
        case ATCMD_ID_NB_MQSUB:
            sprintf(app->network.txbuf, ATCMD_STR_NB_MQSUB, TCFG_MQTT_SUBTOPIC_STR, (int)TCFG_MQTT_SUB_QOS);    // 第一个参数topic,第二个参数Qos:0 1 2
            break;
        case ATCMD_ID_NB_MQPUB:
        {
            // TODO: NBiot模块发布数据是十六进制字符串
            // sprintf(app->network.txbuf, ATCMD_STR_NB_MQPUB, TCFG_MQTT_PUBTOPIC_STR, (int)4, "61626364");
            mqtt_payload_generate(app);
            // log_d("payload len:%d\n", (int)app->network.payload_len);
            log_d("data:%s\n", app->network.payload_buf);

            app->network.txlen = 0;
            memset(app->network.txbuf, 0, sizeof(app->network.txbuf));
            string_to_hex(app->network.payload_buf, app->network.txbuf, app->network.payload_len);
            // log_d("\nHEX:%s\n", app->network.txbuf);
            // log_d("HEX LEN:%d\n", (int)strlen(app->network.txbuf));

            memset(app->network.payload_buf, 0, sizeof(app->network.payload_buf));
            sprintf(app->network.payload_buf, "%s", app->network.txbuf);
            // log_d("\nHEX:%s\n", app->network.payload_buf);
            // log_d("LEN:%d\n", (int)strlen(app->network.payload_buf));

            app->network.txlen = 0;
            memset(app->network.txbuf, 0, sizeof(app->network.txbuf));
            sprintf(app->network.txbuf, ATCMD_STR_NB_MQPUB, TCFG_MQTT_PUBTOPIC_STR,(int)TCFG_MQTT_PUB_QOS,(int)app->network.payload_len, app->network.payload_buf);
        }            
            break;
        case ATCMD_ID_NB_MQUNSUB:
            sprintf(app->network.txbuf, ATCMD_STR_NB_MQUNSUB, (int)at_arg, TCFG_MQTT_SUBTOPIC_STR);
            break;
        case ATCMD_ID_NB_MQDISCON:
            sprintf(app->network.txbuf, ATCMD_STR_NB_MQDISCON, (int)at_arg);
            break;
#endif
        default:
            return;
    }

    // TODO: AT命令串口发送命令
    log_d("AT CMD Send:%s, %d\n", app->network.txbuf, (int)strlen(app->network.txbuf)); // FOR DEBUG
    app->network.atcmd.list[app->network.atcmd.action_idx].cmd_state = AT_WAITING;      /* 重要影响AT指令队列出队机制！！！ */
    app->network.txlen = strlen(app->network.txbuf);
    network_atcmd_uart_send(app->network.txbuf, app->network.txlen);
}

/// @brief 检查AT命令回复是否成功
/// @param app 
/// @param _str 
/// @return 
uint8_t check_atcmd_ok(struct app_t *app, char* _str)
{
    // log_d("check cmd:%s\n", app->network.rxbuf);
    if (strstr(app->network.rxbuf, _str) != NULL) {
        return 1;
    } else {
        return 0;
    }
}

/**
 * @brief   解析MQTT接收数据
 * @param   app:参考@struct app_t
 * @param   _str:接收消息数据字符串
 * @return  无
*/
void analyse_mqtt_recv_messagge(struct app_t* app, char * _str)
{

}
/**
 * @brief   4G CAT1模块AT命令Respons接收
 * @param   atrecv: 1接收AT回复数据，0：接收4G模块主动发送数据
 * @return  无
*/
void network_atcmd_recv_task(struct app_t* app, uint8_t atrecv)
{
    uint8_t recv_end=0;
    int result = 0;
    int at_errcode=0;  // AT命令错误码
    char* _str=NULL;
 

    uint8_t is_timeout=0;
    uint8_t _atcmd_id=0;
    uint8_t _atcmd_arg=0;
    uint8_t success_ok =0;  // 1:AT指令执行成功，但不代表AT指令功能响应成功。通常返回OK
    uint8_t response_ok=0;  // 1:AT指令功能响应OK。通常返回AT指令相关字符串
    
    // TODO: 优先尝试解析模块主动发送的数据
    {
        // TODO: 收到串口数据更新一次接收计时，数据接收完等待指定时间没收到新数据认为一帧数据接收完成
        app->network.recv_diff = jiffes_diff_now(&app->network.recv_starttime);
        if ((app->network.recv_diff >= TCFG_ATCMD_RECV_FRAME_MS) && (app->network.rxlen > 0)) {
            // TODO: 完整接收到AT Response数据，在这里解析处理返回数据
            // log_d("\nM Recv:%s\n", app->network.rxbuf);
            // log_d("recv_diff:%d\n", (int)app->network.recv_diff);

        #if TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_4G
            _str = strstr(app->network.rxbuf, "*ATREADY: 1");
            if ((_str != NULL)&&(strncmp(_str, "*ATREADY: 1", strlen("*ATREADY: 1")) == 0)) {
                // log_d("4G CAT1 AT Ready\n");
                app->network.at_ready = 1;
                recv_end = 1;
            }

            if ((_str != NULL)&&(strncmp(app->network.rxbuf, "\r\n+CPIN: READY", strlen("\r\n+CPIN: READY")) == 0)) {
                // log_d("4G CAT1 SIM Card Insert\n");
                app->network.at_ready = 1;
                app->network.simcardin = 1;
                recv_end = 1;
            }

            // +CPIN: READY
            // +CME ERROR: SIM not inserted
            if ((_str != NULL)&&(strncmp(app->network.rxbuf, "\r\n+CPIN: SIM REMOVED", strlen("\r\n+CPIN: SIM REMOVED")) == 0)) {
                // log_d("4G CAT1 SIM Card Removed\n");
                app->network.at_ready = 1;
                app->network.simcardin = 0;
                recv_end = 1;
            }

            // +CMQTTRECV: 0,"ssht_gas_control",20,"1,4000,10000,150,300    4G消息内容
            _str = strstr(app->network.rxbuf, "+CMQTTRECV:"); // +CMQTTRECV: 0,"topic_cat1_server",4,"test"
            if (_str != NULL) {
                log_d("MQTT RECV:%s\n", _str);
                analyse_mqtt_recv_messagge(app, _str);
                recv_end = 1;
            }
        #elif TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_NB
            // TODO: NB模块
            // 有SIM卡 ^SIMST:1
            // 深睡唤醒不做卡初始化：^SIMST:2 
            // 无SIM卡 ^SIMST:0
            _str = strstr(app->network.rxbuf, "SIMST:");
            if (NULL != _str) {
                int cardin=0;
                result = sscanf(_str, "SIMST:%d[0-2]", &cardin);
                app->network.at_ready = 1;
                if (0 == cardin) {
                    app->network.simcardin = 0;
                } else if (1 == cardin) {                    
                    app->network.simcardin = 1;
                } else if (2 == cardin) {

                }
                recv_end = 1;
                // log_d("simcardin:%d\n", (int)app->network.simcardin);
            }
            
            #if 0
            // TODO: MQTT 服务断开
            // +MQCON:0 disconnect
            _str = strstr(app->network.rxbuf, "+MQCON:0 disconnect");
            if (NULL != _str) {
                log_d("====> MQTT DISCONNECT!!!\n");
                network_server_reconnect(app);
                recv_end = 1;
            }

            // +MQDISON:
            _str = strstr(app->network.rxbuf, "+MQDISON:");
            if (NULL != _str) {
                log_d("====> MQTT MQDISON !!!\n");
                network_server_reconnect(app);
                recv_end = 1;
            }
            #endif
            
            // TODO: MQTT 服务器下发数据
            // +MQPUB:0,topic_cat1_server,0,0,0,5,4E42494F54    数据内容是：NBIOT
            _str = strstr(app->network.rxbuf, "+MQPUB:");
            if (NULL != _str) {
                // TODO:解析接收到的消息
                log_d("MQTT Recv:%s\n", _str);
                analyse_mqtt_recv_messagge(app, _str);
                recv_end = 1;
            }            
        #endif

            // TODO: 清空接收缓存，等待下一次接收4G模块发送数据
            if ((1 == recv_end)||!atrecv) {
                log_d("rxbuf:%s\n", app->network.rxbuf);
                app->network.rxlen = 0;
                memset(app->network.rxbuf, 0, sizeof(app->network.rxbuf));
                // log_d("recv_end clear rxbuf 111\n");
            }            
        }
    }
    
    if (atrecv) {
        // TODO: AT命令回复消息
        app->network.recv_diff = jiffes_diff_now(&app->network.jsendtime);        
        _atcmd_id = app->network.atcmd.list[app->network.atcmd.action_idx].cmd_id;
        _atcmd_arg = app->network.atcmd.list[app->network.atcmd.action_idx].arg;
        success_ok = check_atcmd_ok(app, app->network.atcmd.list[app->network.atcmd.action_idx].success_str);
        response_ok = check_atcmd_ok(app, app->network.atcmd.list[app->network.atcmd.action_idx].response_str);
        
        // TODO: AT指令超时判断
		if (app->network.recv_diff >= app->network.atcmd.list[app->network.atcmd.action_idx].timeout) {
            is_timeout = 1;
        } else {
            is_timeout = 0;
        }

        // 从接收到第一个字节的时间开始，超过50ms认为本次数据接收完成。
        if (success_ok || is_timeout) {
            // log_d("AT Recv:%s", app->network.rxbuf);
            // log_d("diff:%d, timeout:%lu\n", diff, app->network.atcmd.list[app->network.atcmd.action_idx].timeout);
            // log_d("response_str:%s\n", app->network.atcmd.list[app->network.atcmd.action_idx].response_str);
        #if 1 // for debug
            if ((success_ok && response_ok)||is_timeout) {
                log_d("AT Recv:%s", app->network.rxbuf);
            }
        #endif
        #if TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_4G
            // TOOD:解析AT命令响应数据
            if (ATCMD_ID_4G_CPIN == _atcmd_id) {
                _str = strstr(app->network.rxbuf, "+CPIN: READY");
                if (strncmp(_str, "+CPIN: READY", strlen("+CPIN: READY")) == 0) {
                    app->network.simcardin = 1;
                }

            } else if (ATCMD_ID_4G_CSQ == _atcmd_id) {
                /*  
                    rssi:
                    0 -113 dBm or less
                    1 -111 dBm
                    2…30 -109… -53 dBm
                    31 -51 dBm or greater
                    99 not known or not detectable
                */
                _str = strstr(app->network.rxbuf, "+CSQ: ");
                if (_str != NULL) {
                    // log_d("_str:%s\n", _str);
                    result = sscanf(_str, "+CSQ: %d,%d", &app->network.rssi, &app->network.ber);
                    // log_d("app->rssi:%d, app->ber:%d\n", app->network.rssi, app->network.ber);
                }
            } else if (ATCMD_ID_4G_CGREG == _atcmd_id) {
                _str = strstr(app->network.rxbuf, "+CGREG: ");
                if (_str != NULL) {
                    // log_d("_str:%s\n", _str);
                    result = sscanf(_str, "+CGREG: %i,%i", &app->network.reg_mode, &app->network.reg_stat);
                }
            } else if (ATCMD_ID_4G_SIMEI == _atcmd_id) {
                _str = strstr(app->network.rxbuf, "+SIMEI: ");
                if (_str != NULL) {
                    result = sscanf(_str, "+SIMEI: %s", app->network.simei);                    
                    memcpy(app->dev_uuid, app->network.simei+2, strlen(app->network.simei)-2);
                    // log_d("simei:%s, result:%d\n", app->network.simei, result);
                    // log_d("dev_uuid:%s\n", app->dev_uuid);
                }
            } else if (ATCMD_ID_4G_CICCID == _atcmd_id) {
                _str = strstr(app->network.rxbuf, "+ICCID: ");
                if (_str != NULL) {
                    app->network.simcardin = 1;
                    result = sscanf(_str, "+ICCID: %s", app->network.ciccid);
                    // log_d("app->ciccid:%s, result:%d\n", app->network.ciccid, result);
                }
            } else if (ATCMD_ID_4G_CTZU_GET == _atcmd_id) {
                _str = strstr(app->network.rxbuf, "+CTZU: ");  // +CTZU: 1
                if (_str != NULL) {
                    int ctzu=0;
                    sscanf(_str, "+CTZU: %d", &ctzu);
                    // log_d("ctzu:%d\n", (int)ctzu);
                    app->network.module_ctzu = ctzu;
                    if (0 == ctzu) {
                        cat1_ctzu_set_atcmd_send(app, 1);
                    } else {

                    }
                }
        #if TCFG_SYNCTIME_BY_MODULE
            } else if (ATCMD_ID_4G_CCLK == _atcmd_id) {
                _str = strstr(app->network.rxbuf, "+CCLK: ");  
                // +CCLK: "24/07/30,15:01:55+32"   +8时区
                // +CCLK: "24/07/30,15:01:55+00"    0时区
                // +CCLK: "24/07/30,15:01:55-32"   -8时区
                if (_str != NULL) {
                    // calendar_obj utc,tz;
                    int _y,_m,_d,_h,_min,_sec,_timezone=0;
                    result = sscanf(_str, "+CCLK: \"%d/%d/%d,%d:%d:%d+%*d\"",&_y, &_m, &_d, &_h, &_min, &_sec);
                    // result = sscanf(_str, "+CCLK: \"%d/%d/%d,%d:%d:%d+%d\"",&_y, &_m, &_d, &_h, &_min, &_sec, &_timezone);
                    
                    // 同步设置网络时间
                    #if 0
                    if (app->network.module_ctzu == 0) {
                        utc.year = _y;
                        utc.mon = _m;
                        utc.date = _d;
                        utc.hour = _h;
                        utc.min = _min;
                        utc.sec = _sec;
                        log_d("UTC TO ZONETIME\n");
                        UTC_to_ZoneTime(&utc, 8, &tz);
                        RTC_Reload(21,tz.year,tz.mon,tz.date,tz.hour,tz.min,tz.sec);
                    } else {
                        RTC_Reload(21,_y,_m,_d,_h,_min,_sec);  
                    }
                    #else
                    if (app->network.module_ctzu == 1) {
                        // log_d("result:%d\n", result);
                        // log_d("RTC SYNC NTP:%d/%d/%d  %d:%d:%d  %d\n",(int)_y, (int)_m, (int)_d, (int)_h, (int)_min, (int)_sec, (int)_timezone);

                        // 错误日期时间+CCLK: "70/01/01,00:00:08+00" 
                        // 正确日期时间+CCLK: "24/10/24,20:54:51+32"
                        if (_y >= 24 && _y <= 60) {
                                // TODO:日期时间正确性检查
                            // RTC_Reload(21,_y,_m,_d,_h,_min,_sec);                               

                            app->rtcntp_synced = 1;    // 设置RTC网络时间已同步
                            app->netinit_step = E_NET_INIT_STEP_2;  // 表示模块初始化成功
                        }
                    }
                    #endif
                }
            #endif
            } else if (ATCMD_ID_4G_CMQTTCONNECT == _atcmd_id) {                
                if (success_ok) {                    
                    //成功 +CMQTTCONNECT: 0,0 
                    int _client_index,_err;
                    _str = strstr(app->network.rxbuf, "+CMQTTCONNECT: "); 
                    if (NULL != _str) {
                        result = sscanf(_str, "+CMQTTCONNECT: %d,%d", (int*)&_client_index, (int*)&_err);
                        // log_d("CMQTTCONNECT  _client_index:%d, _err:%d\n", (int)_client_index, (int)_err);
                        if (_err == 0) {
                            // log_d("mqtt CMQTTCONNECT ok\n");
                            app->network.mqtt_connected = 1;
                        } else {
                            // log_d("mqtt CMQTTCONNECT err\n");
                            network_server_reconnect(app);
                        }
                    }          
                }  else {
                    // TODO: 重新连接
                    if (is_timeout) {
                        // log_d("mqtt CMQTTCONNECT timeout\n");
                        network_server_reconnect(app);
                    }
                }
                // log_d("mqtt_connected:%d\n", app->network.mqtt_connected);

            } else if (ATCMD_ID_4G_CMQTTPAYLOAD == _atcmd_id) {
                if (response_ok) {
                    network_atcmd_uart_send(app->network.payload_buf, app->network.payload_len);
                    log_d("4G MQTT input:%s\n", app->network.payload_buf);
                } else if (is_timeout) {
                    // log_d("4G_CMQTTPAYLOAD timeout\n");
                    app->network.mqtt_senderr_cnt++;
                }
                // response_ok = 1;

            } else if (ATCMD_ID_4G_CMQTTPUB == _atcmd_id) {
                if (response_ok) {
                    // log_d("4G_CMQTTPUB RESPONSE OK\n");
                    // MQTT发布消息成功 +CMQTTPUB: 0,0
                    // MQTT发布消息失败 +CMQTTPUB: 0,11
                    _str = strstr(app->network.rxbuf, "+CMQTTPUB: ");
                    if (_str != NULL) {
                        int _client_index,_err;
                        result = sscanf(_str, "+CMQTTPUB: %d,%d", &_client_index, &_err);
                        // log_d("_client_index:%d, _err:%d\n", _client_index, _err);
                        if (_err == 0) {
                            // log_d("mqtt publish ok\n");
                            app->network.mqtt_senderr_cnt = 0;
                        } else {
                            app->network.mqtt_senderr_cnt++;
                            // log_d("mqtt publish err cnt:%d\n", (int)app->network.mqtt_senderr_cnt);                            
                        }
                    }
                } else if (is_timeout) {
                    app->network.mqtt_senderr_cnt++;
                    // log_d("4G_CMQTTPUB timeout:%d\n", (int)app->network.mqtt_senderr_cnt);
                }
            }
        #elif TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_NB
            // +CME ERROR:8002
            _str = strstr(app->network.rxbuf, "+CME ERROR:");
            if (NULL != _str) {
                result = sscanf(_str, "+CME ERROR:%i[0-9]", &at_errcode);
                // log_d("AT ERRORCODE:%d\n", at_errcode);
            #if 0
                switch(at_errcode)
                {
                    case 8000:  // 需要进行设备重启
                        // log_d("NB-Iot need reset\n");
                        break;
                    case 8001:  // 输入的 AT 命令参数不合法
                        // log_d("AT param error\n");
                        break;
                    case 8002:  // 操作不允许，通常为状态机不符合
                        // log_d("AT status not inconformity\n");
                        break;
                    case 8003:  // AT 命令丢失或字符脏，常见于 standby 唤醒时 PLL 不稳造成的
                        break;
                    case 8004:  // 当前正在进行 FOTA 升级，不接受其他操作控制
                        break;
                    case 8005:  // 暂未使用
                        break;
                    case 8006:  // 等待 AT 应答超时，需要将等待时长设大
                        break;
                    case 8007:  // AT 通道忙，上一条 AT 请求尚未处理完
                        log_d("AT busy!\n");
                        break;
                    case 8008:  // 当前为单核模式，仅 M3 核正常工作，错误的发送需要 DSP 核处理的 AT 命令
                        break;
                    case 8009:  // NB 网络异常，tcpip 网路不通畅
                        log_d("NB network abnormal!\n");
                        break;
                    case 8010:  // 发 生 断 电 ， 需 要 输 入 
                        break;
                    case 8012:  // 前缀无效。如：AT+XXX=?QQQ 和 AT+XXX?QQQ
                        break;
                    case 9000:  // 用户自定义扩展错误码起始值
                        break;
                    default:
                        break;
                }

                // TODO: 连接MQTT命令出错，再次重连MQTT
                if (ATCMD_ID_NB_MQCON == _atcmd_id) {
                    log_d("at error, mqtt connect again\n");
                    network_server_reconnect(app);
                }
            #endif 
                // TODO: 接收到错误码之后，清除一次接收缓冲
                app->network.rxlen = 0;
                memset(app->network.rxbuf, 0, sizeof(app->network.rxbuf));      
            }

            if (ATCMD_ID_NB_CIMI == _atcmd_id) {
                // 存储在卡中的IMSI值
                // +CIMI:460045506610864 
                _str = strstr(app->network.rxbuf, "+CIMI:");
                if (NULL != _str) {
                    result = sscanf(_str, "+CIMI:%s", app->network.simsi);
                    // log_d("simsi:%s, result:%d\n", app->network.simsi, result);
                }
            } else if (ATCMD_ID_NB_NCCID == _atcmd_id) {
                _str = strstr(app->network.rxbuf, "+NCCID:");
                if (NULL != _str) {
                    app->network.simcardin = 1;
                    result = sscanf(_str, "+NCCID:%s", app->network.ciccid);
                    // log_d("ciccid:%s, result:%d\n", app->network.ciccid, result);
                }
            } else if (ATCMD_ID_NB_CGSN == _atcmd_id) {
                // log_d("_atcmd_arg:%d\n", (int)_atcmd_arg);
                if (0 == _atcmd_arg) {
                    // TODO: 模块SN     MP0622228516BC5  OK
                    _str = strstr(app->network.rxbuf, "\r\n");
                    if (NULL != _str) {
                        log_d("%s\n", _str);
                    }
                } else if (1 == _atcmd_arg) {
                    // TODO: 模块IMEI   +CGSN:866808067789932   OK
                    _str = strstr(app->network.rxbuf, "+CGSN:");
                    if (NULL != _str) {
                        result = sscanf(_str, "+CGSN:%s", app->network.simei);                    
                        memcpy(app->dev_uuid, app->network.simei+2, strlen(app->network.simei)-2);
                        // log_d("simei:%s, result:%d\n", app->network.simei, result);
                        // log_d("dev_uuid:%s\n", app->dev_uuid);
                    }
                } else if (2 == _atcmd_arg) {
                    // TODO: 模块IMEISV

                } else if (3 == _atcmd_arg) {
                    // TODO: 模块SVN
                }
        #ifdef ATCMD_STR_NB_CGATT
            } else if (ATCMD_ID_NB_CGATT == _atcmd_id) {
                // +CGATT:1
                _str = strstr(app->network.rxbuf, "+CGATT:");
                if (_str != NULL) {
                    result = sscanf(_str, "+CGATT:%d", &app->network.gatt);
                    // log_d("gatt:%d, result:%d\n", app->network.gatt, result);
                }
        #endif
            } else if (ATCMD_ID_NB_CGMR == _atcmd_id) {
                log_d("%s\n", app->network.rxbuf);

            } else if (ATCMD_ID_NB_CEREG == _atcmd_id) {
                // +CEREG:0,1
                _str = strstr(app->network.rxbuf, "+CEREG:");
                if (_str != NULL) {
                    // log_d("_str:%s\n", _str);
                    result = sscanf(_str, "+CEREG:%i,%i", &app->network.reg_mode, &app->network.reg_stat);
                    // log_d("reg_mode:%d, reg_stat:%d\n", app->network.reg_mode, app->network.reg_stat);
                }
            } else if (ATCMD_ID_NB_CESQ == _atcmd_id) {

            } else if (ATCMD_ID_NB_CSQ == _atcmd_id) {
                // +CSQ:22,99
                _str = strstr(app->network.rxbuf, "+CSQ:");
                if (_str != NULL) {
                    // log_d("_str:%s\n", _str);
                    result = sscanf(_str, "+CSQ:%d,%d", &app->network.rssi, &app->network.ber);
                    // log_d("rssi:%d, ber:%d\n", app->network.rssi, app->network.ber);
                }
        #if TCFG_SYNCTIME_BY_MODULE
            } else if (ATCMD_ID_NB_CCLK == _atcmd_id) {
                // +CCLK:24/08/13,10:14:38+32                
                _str = strstr(app->network.rxbuf, "+CCLK:");
                if (_str != NULL) {
                    calendar_obj utc,tz;
                    int _y,_m,_d,_h,_min,_sec;
                    result = sscanf(_str, "+CCLK:%d/%d/%d,%d:%d:%d+%*d",&_y, &_m, &_d, &_h, &_min, &_sec);
                    utc.year = _y;
                    utc.mon = _m;
                    utc.date = _d;
                    utc.hour = _h;
                    utc.min = _min;
                    utc.sec = _sec;
                    UTC_to_ZoneTime(&utc, 8, &tz);

                    // TODO:设置RTC日期时间
                    // RTC_Reload(21,tz.year,tz.mon,tz.date,tz.hour,tz.min,tz.sec);

                    log_d("RTC NTP SYNCED:%d/%d/%d  %d:%d:%d\n", (int)tz.year, (int)tz.mon, (int)tz.date, (int)tz.hour, (int)tz.min, (int)tz.sec);
                    // log_d("UTC:%d/%d/%d  %d:%d:%d\n", (int)utc.year, (int)utc.mon, (int)utc.date, (int)utc.hour, (int)utc.min, (int)utc.sec);
                    // log_d("TZO:%d/%d/%d  %d:%d:%d\n", (int)tz.year, (int)tz.mon, (int)tz.date, (int)tz.hour, (int)tz.min, (int)tz.sec);                
                
                    app->rtcntp_synced = 1;    // 设置RTC网络时间已同步
                    app->netinit_step = E_NET_INIT_STEP_2;  // 表示模块初始化成功
                }
        #endif                
            } else if (ATCMD_ID_NB_MQNEW == _atcmd_id) {

            } else if (ATCMD_ID_NB_MQCON == _atcmd_id) {
                if (response_ok) {
                    app->network.mqtt_connected = 1;
                    // log_d("mqtt_connected:%d\n", (int)app->network.mqtt_connected);
                } else {
                    // TODO: 重新连接
                    if (is_timeout) {
                        // log_d("mqtt connect error\n");
                        network_server_reconnect(app);
                    }
                }

            } else if (ATCMD_ID_NB_MQSUB == _atcmd_id) {
                if (response_ok) {
                    // log_d("mqtt subscribe ok\n");
                }
            } else if (ATCMD_ID_NB_MQPUB == _atcmd_id) {
                if (response_ok) {
                    // log_d("\nmqtt publish ok\n");
                    app->network.mqtt_senderr_cnt = 0;
                } else if (is_timeout) {
                    // log_d("mqtt publish err cnt:%d\n", (int)app->network.mqtt_senderr_cnt);
                    app->network.mqtt_senderr_cnt++;                    
                }
            
            }
        #endif

            if (response_ok) {
                // TODO: AT指令执行成功，功能OK
                app->network.atcmd.list[app->network.atcmd.action_idx].cmd_state = AT_SUCCESS;
                app->network.atcmd.list[app->network.atcmd.action_idx].trys = 0;
                log_d("===AT SUCCESS==>\n");

            } else if (is_timeout) {
                // TODO: AT指令超时
                app->network.atcmd.list[app->network.atcmd.action_idx].cmd_state = AT_TIMEOUT;
                log_d("===AT TIMEOUT==>\n");
            }
            
            // TODO: 本次AT指令执行成功或超时，清空接收缓存，等待下一次接收4G模块发送数据
            if ((success_ok && response_ok) || is_timeout) {
                // log_d("success_ok:%d,  response_ok:%d, is_timeout:%d\n",(int)success_ok, (int)response_ok, (int)is_timeout);
                // log_d("rxbuf:%s\n", app->network.rxbuf);
                // log_d("recv_end clear rxbuf 222\n");
                app->network.rxlen = 0;
                memset(app->network.rxbuf, 0, sizeof(app->network.rxbuf));
            }  
        }

    }

}

/**
 * @brief   网络模块AT指令处理任务
 * @param   app:参考@struct app_t
 * @return  无
*/
void network_atcmd_process_task(struct app_t* app)
{
    int32_t at_diff = 0;
    static uint32_t at_delay=0; // 保存当前发送的AT指令指定延时多长时间才能发送下一条AT指令

    at_diff = jiffes_diff_now(&app->network.jsendtime);

    if (AT_STATUS_IDLE == app->network.atcmd.status) {
        // TODO: AT命令处于IDLE空闲状态, 主要用于接收4G模块主动发送的数据
        network_atcmd_recv_task(app, 0);

    } else if (AT_STATUS_SENDING == app->network.atcmd.status) {
        if (((app->network.recv_diff < TCFG_ATCMD_RECV_FRAME_MS) && (app->network.rxlen > 0)) \
            &&(AT_STATUS_WAITING != app->network.atcmd.status)) {
            // TODO: 正在接收网络模块主动上报数据
            network_atcmd_recv_task(app, 0);
        } else {
            // TODO: AT 命令处于发送状态，主要用于接收4G模块AT命令之后响应数据
            if (app->network.atcmd.action_idx == app->network.atcmd.size) {
                // TODO: AT执行命令索引 等于 队列长度 索引从0开始
                app->network.atcmd.action_idx = 0;
            }
            if (app->network.atcmd.action_idx == app->network.atcmd.append_idx) {
                // TODO: 执行队列索引 等于 当前入队位置表示 AT队列全部出队
                // log_d("======> 111 goto AT_STATUS_IDLE mode\n");
                app->network.atcmd.status = AT_STATUS_IDLE;

            } else {
                // TODO: 上次发送时间大于最小发送周期，同时大于当前AT指令延时时间
                if ((at_diff >= TCFG_ATCMD_SENDTASK_PERIOD_MS)&&(at_diff >= at_delay)) {
                    if ((AT_WAITING == app->network.atcmd.list[app->network.atcmd.action_idx].cmd_state)) {
                        // TODO: 当前发送的AT指令处于等待AT响应状态
                        app->network.atcmd.status = AT_STATUS_WAITING;  // AT命令发送之后，状态设置为等待AT回复

                    } else if ((ATCMD_ID_UNKNOW != app->network.atcmd.list[app->network.atcmd.action_idx].cmd_id)) {
                        // TODO: 有效AT命令 执行发送
                        #if 0   // FOR DEBUG
                        log_d("----> _diff:%d, at command send  action_idx:%d, append_idx:%d\n", (int)at_diff, \
                            (int)app->network.atcmd.action_idx, \
                            (int)app->network.atcmd.append_idx);
                        #endif
                        network_atcmd_send_process(app);        // 执行AT命令发送过程
                        jiffes_get(&app->network.jsendtime);         // 获取AT命令发送时间，用于计算发送超时
                        at_delay = app->network.atcmd.list[app->network.atcmd.action_idx].delay; // 本次发送的AT指令延时时间
                        app->network.atcmd.status = AT_STATUS_WAITING;  // AT命令发送之后，状态设置为等待AT回复
                    }
                }
            }
        }
    } else if (AT_STATUS_WAITING == app->network.atcmd.status) {
        // TODO：AT 命令处于等待状态（发送完AT命令 等待接收回复）
        network_atcmd_recv_task(app, 1);

        if (AT_SUCCESS == app->network.atcmd.list[app->network.atcmd.action_idx].cmd_state) {
            // TODO: AT命令响应数据接收成功
            app->network.atcmd.list[app->network.atcmd.action_idx].cmd_id = ATCMD_ID_UNKNOW; // 当前AT命令执行结束，ID设为无效
            app->network.atcmd.action_idx++; // 发送下一条AT命令
            app->network.atcmd.status = AT_STATUS_SENDING;
            // log_d("====>AT_SUCCESS append action_idx:%d, append_idx:%d, list size:%d\n", (int)app->network.atcmd.action_idx,  (int)app->network.atcmd.append_idx, (int)app->network.atcmd.size);           
        } else if (AT_TIMEOUT == app->network.atcmd.list[app->network.atcmd.action_idx].cmd_state) {
            // TODO: AT命令响应数据接收超时，重复次数大于0，尝试重复发送当前AT命令
            // log_d("====>AT_TIMEOUT append action_idx:%d, append_idx:%d\n", (int)app->network.atcmd.action_idx, (int)app->network.atcmd.append_idx);
            if (app->network.atcmd.list[app->network.atcmd.action_idx].trys > 0) {
                // log_d("AT AT_TIMEOUT TRYS SEND, trys:%d\n", (int)app->network.atcmd.list[app->network.atcmd.action_idx].trys);
                app->network.atcmd.list[app->network.atcmd.action_idx].cmd_state = AT_NORECV;
                app->network.atcmd.list[app->network.atcmd.action_idx].trys--;
                app->network.atcmd.status = AT_STATUS_SENDING;
            } else {
                // TODO: AT命令响应数据接收超时，且重复次数等于0，发送下一条命令
                // log_d("AT AT_TIMEOUT TRYS ===> 0\n");
                app->network.atcmd.list[app->network.atcmd.action_idx].cmd_id = ATCMD_ID_UNKNOW; // 当前AT命令执行结束，ID设为无效
                app->network.atcmd.action_idx++; // 发送下一条AT命令
                app->network.atcmd.status = AT_STATUS_SENDING;
            }
        }
    }

}


/**
 * @brief   清空AT指令列表
 * @param   app参考@struct app_t
 * @return  无
*/
void network_atcmd_list_clear(struct app_t* app)
{
    uint8_t i=0;
    app->network.atcmd.action_idx = 0;
    app->network.atcmd.append_idx = 0;
    for (i=0; i<AT_CMD_LIST_LEN; i++) {
        app->network.atcmd.list[i].timeout = 0;
        app->network.atcmd.list[i].trys = 0;
        app->network.atcmd.list[i].cmd_id = ATCMD_ID_UNKNOW;
        app->network.atcmd.list[i].cmd_state = AT_NORECV;
    }
    app->network.atcmd.status = AT_STATUS_IDLE;
}

//  enqueue dequeue



// network_atcmd_enqueue(app, ATCMD_ID_NB_MQNEW, 0, "OK\r\n", "+MQNEW", 10000, 1000, 0);    // 响应数据OK在尾部 
// network_atcmd_enqueue(app, ATCMD_ID_NB_MQCON, 0, "+MQCONNACK", "+MQCONNACK", 10000, 1000, 0);   // 响应数据比较特殊OK在头部  "OK\r\n+MQCONNACK"
/**
 * @brief   添加一条AT指令到AT命令队列
 * @param   app:参考@struct app_t
 * @param   cmd_id: AT指令ID
 * @param   success_str: AT指令发送成功回复字符串，仅表示本次AT命令发送成功
 * @param   response_str：AT指令功能成功回复字符串，表示本次AT命令功能成功
 * @param   timeout: AT指令等待回复超时时间
 * @param   delay: 延时多长时间才能发送下一条AT指令，单位毫秒
 * @param   trys: AT指令发送失败，尝试发送次数
*/
void network_atcmd_enqueue(struct app_t* app, uint8_t cmd_id, uint8_t arg, char* success_str, char* response_str, uint32_t timeout, uint32_t delay, uint8_t trys)
{
    app->network.atcmd.list[app->network.atcmd.append_idx].cmd_id = cmd_id;
    app->network.atcmd.list[app->network.atcmd.append_idx].arg = arg;
    app->network.atcmd.list[app->network.atcmd.append_idx].timeout = timeout;
    app->network.atcmd.list[app->network.atcmd.append_idx].delay = delay;
    app->network.atcmd.list[app->network.atcmd.append_idx].trys = trys;
    app->network.atcmd.list[app->network.atcmd.append_idx].cmd_state = AT_NORECV;
    strcpy(app->network.atcmd.list[app->network.atcmd.append_idx].success_str, success_str);
    strcpy(app->network.atcmd.list[app->network.atcmd.append_idx].response_str, response_str);
    app->network.atcmd.append_idx++;

    if (app->network.atcmd.append_idx == app->network.atcmd.size) {
        app->network.atcmd.append_idx = 0;
    }

    app->network.atcmd.status = AT_STATUS_SENDING;  // 设置AT命令队列发送状态
}


#if TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_4G
/**
 * @brief   获取日期时间自动更新设置
 * @param   app:参考@struct app_t
 * @return  无
 */
void cat1_ctzu_get_atcmd_send(struct app_t* app)
{
    network_atcmd_enqueue(app, ATCMD_ID_4G_CTZU_GET, 0, "OK", "+CTZU", 2000, 1000, 3);
}

/**
 * @brief   设置日期时间自动更新
 * @param   app参考@struct app_t
*/
void cat1_ctzu_set_atcmd_send(struct app_t* app, uint8_t arg)
{
    network_atcmd_enqueue(app, ATCMD_ID_4G_CTZU_SET, arg, "OK", "OK", 2000, 3000,  0);
#ifdef ATCMD_STR_4G_CRESET
    network_atcmd_enqueue(app, ATCMD_ID_4G_CRESET, 0, "OK", "OK", 3000, 10000,  5);
#endif
}

/**
 * @brief   网络状态查询
 * @param   app参考@struct app_t
*/
void cat1_network_check_atcmd_send(struct app_t* app)
{
    network_atcmd_enqueue(app, ATCMD_ID_4G_CSQ, 0, "OK", "+CSQ",1000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 0);

    network_atcmd_enqueue(app, ATCMD_ID_4G_CGREG, 0, "OK", "+CGREG", 1000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 0);

    if (0 == app->network.simcardin) {
        network_atcmd_enqueue(app, ATCMD_ID_4G_CPIN, 0, "OK", "+CPIN", 1000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 0);
    }    

    if (strlen(app->dev_uuid) == 0) {
        network_atcmd_enqueue(app, ATCMD_ID_4G_SIMEI, 0, "OK", "+SIMEI", 3000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 2);
    }

    if (strlen(app->network.ciccid) == 0) {
        network_atcmd_enqueue(app, ATCMD_ID_4G_CICCID, 0, "OK", "+CICCID", 3000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 2);
    }
}

/**
 * @brief   MQTT初始化
 * @param   app参考@struct app_t
 * @return  无
 * @note    启动MQTT服务，连接MQTT服务器，订阅MQTT
*/
void cat1_mqtt_connect_atcmd_send(struct app_t* app)
{
    network_atcmd_enqueue(app, ATCMD_ID_4G_CMQTTSTART, 0, "OK", "+CMQTTSTART", 3000, 500, 0);
    network_atcmd_enqueue(app, ATCMD_ID_4G_CMQTTACCQ, 0, "OK", "+CMQTTACCQ", 3000, 500, 0);
    network_atcmd_enqueue(app, ATCMD_ID_4G_CMQTTCFG_VER, 0, "OK", "+CMQTTCFG=\"version\"", 3000, 500, 0);
    network_atcmd_enqueue(app, ATCMD_ID_4G_CMQTTCFG_ARG, 0, "OK", "+CMQTTCFG=\"argtopic\"", 3000, 500, 0);
    network_atcmd_enqueue(app, ATCMD_ID_4G_CMQTTCONNECT, 0, "OK", "+CMQTTCONNECT", 10000, 500, 0);
    network_atcmd_enqueue(app, ATCMD_ID_4G_CMQTTSUB, 0, "OK", "+CMQTTSUB", 10000, 500, 0);
}


/**
 * @brief   4G模块关机指令
 * @param   app参考@struct app_t
 * @return  无
*/
void cat1_poweroff_atcmd_send(struct app_t* app)
{
    network_atcmd_enqueue(app, ATCMD_ID_4G_CPOF, 0, "OK", "OK", 1000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 3);
}

void cat1_cfunc_atcmd_send(struct app_t* app, uint8_t arg)
{
    network_atcmd_enqueue(app, ATCMD_ID_4G_CFUNC, arg, "OK", "OK", 1000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 3);
}

#elif TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_NB

void nbiot_module_info_get(struct app_t* app)
{
    if (strlen(app->dev_uuid) == 0) {
        network_atcmd_enqueue(app, ATCMD_ID_NB_CGSN, 1, "OK", "+CGSN", 3000, 1000, 0);    // IMEI号
    }

    if (strlen(app->network.ciccid) == 0) {
        network_atcmd_enqueue(app, ATCMD_ID_NB_NCCID, 0, "OK", "+NCCID", 3000, 1000, 0);   // SIM卡ID号 
        // network_atcmd_enqueue(app, ATCMD_ID_NB_CIMI, 0, "OK", "+CIMI", 3000, 1000, 0);    // 存储在卡中的IMSI值              
    }
}


/**
 * @brief   NB-iot网络状态查询
 * @param   app参考@struct app_t
*/
void nbiot_network_check_atcmd_send(struct app_t* app)
{
    nbiot_module_info_get(app);

    network_atcmd_enqueue(app, ATCMD_ID_NB_CSQ, 0, "OK", "+CSQ", 3000, 1000, 0);
#ifdef ATCMD_STR_NB_CGATT
    // network_atcmd_enqueue(app, ATCMD_ID_NB_CGATT, 0, "OK", "+CGATT", 3000, 1000, 0); // 这个命令会影响RF指标性能！！
#endif    
    network_atcmd_enqueue(app, ATCMD_ID_NB_CEREG, 0, "OK", "+CEREG", 3000, 1000, 0);
}

void nbiot_mqtt_connect_atcmd_send(struct app_t* app)
{
    // nbiot_module_info_get(app);

    #if 0
    // TODO: 先断开MQTT连接
    network_atcmd_enqueue(app, ATCMD_ID_NB_MQUNSUB, 0, "OK", "OK", 3000, 3000, 3);
    network_atcmd_enqueue(app, ATCMD_ID_NB_MQDISCON, 0, "OK", "OK", 3000, 3000, 3);
    #endif
    
    // TODO: 创建连接 MQTT
    network_atcmd_enqueue(app, ATCMD_ID_NB_MQNEW, 0, "OK", "+MQNEW", 10000, 3000, 0);
    network_atcmd_enqueue(app, ATCMD_ID_NB_MQCON, 0, "OK", "+MQCONNACK", 10000, 3000, 0);   // 响应数据比较特殊OK在前  "OK\r\n+MQCONNACK"
    network_atcmd_enqueue(app, ATCMD_ID_NB_MQSUB, 0, "OK", "+MQSUBACK", 10000, 3000, 0);
}

void nbiot_poweroff_atcmd_send(struct app_t* app)
{
    #ifdef ATCMD_STR_NB_FASTOFF
    network_atcmd_enqueue(app, ATCMD_ID_NB_FASTOFF, 0, "OK", "+POWERDOWN", 5000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 0);
    #endif
}

#ifdef ATCMD_STR_NB_CPSMS
void nbiot_psmmode_atcmd_send(struct app_t* app, uint8_t psmmode)
{
    network_atcmd_enqueue(app, ATCMD_ID_NB_CPSMS, psmmode, "OK", "OK", 5000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 0);
}
#endif

#ifdef ATCMD_STR_NB_CPSMS_GET
void nbiot_psmmode_get_atcmd_send(struct app_t* app)
{
    network_atcmd_enqueue(app, ATCMD_ID_NB_CPSMS_GET, 0, "OK", "+CPSMS", 5000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 0);
} 
#endif

#endif

void network_checking_reconnect(struct app_t* app)
{
    if (app->network.mqtt_senderr_cnt >= TCFG_MQTT_ERROR_RECONNECT_CNT) {
        // TODO: MQTT发送N次失败，认为MQTT连接出错，重新连接MQTT
        network_server_reconnect(app);
    }

    if (1 == app->mqttrecon) {
        app->mqttrecon = 0;

        // log_d("do mqtt reconnect\n");
        app->network.mqtt_senderr_cnt = 0;
        app->network.mqtt_connected = 0;
        app->rtcntp_synced = 0; /* 每次联网同步一次RTC时间 */
        app->status_synced = 0;
        app->network.reg_stat = 0;
        app->network.gatt = 0;
        app->network.rssi = 0;
        app->network.at_ready = 0;

        app->netinit_step = E_NET_INIT_STEP_1;    /* 模块RESET拉低 */
        #if TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_4G
        // 4G模块 MQTT重连之前 拉低RESET引脚复位 2.5S低电平
        log_d("======>4G RESET LOW\n");
        NET_RST_LOW();
        jiffes_now_add_ms(&app->network.jnetrst, TCFG_REST_LOW_TIME_S);
        #elif TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_NB
        // NB模块 MQTT重连之前 直接掉电
        log_d("======>NB RESET LOW\n");
        // NET_POWER_OFF();
        NET_RST_LOW();
        jiffes_now_add_ms(&app->network.jnetrst, TCFG_REST_LOW_TIME_S);
        #endif

        // TODO: 模块重连之前先清空AT命令队列
        network_atcmd_list_clear(app);
    }
}

/**
 * @brief   网络模块启动MQTT重连机制
*/
void network_server_reconnect(struct app_t* app)
{
    app->mqttrecon = 1;
    app->network.net_connecting = 0;
}

/**
 * @brief   网络模块上报数据
 * @param   app:参考@struct app_t
 * @param   msg_type: 上报数据消息类型
 */
void network_mqtt_report_atcmd_send(struct app_t* app, uint8_t msg_type)
{
    app->network.msg_type = msg_type;
    #if TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_4G
    /* 4G 模块上报MQTT消息数据 */
    network_atcmd_enqueue(app, ATCMD_ID_4G_CMQTTPAYLOAD, 0, ">", ">", 5000, 500, 0);
    network_atcmd_enqueue(app, ATCMD_ID_4G_CMQTTPUB, 0, "OK", "+CMQTTPUB:", 5000, 1000, 0);
    #elif TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_NB
    /* NB 模块上报MQTT消息数据 */
    #if 2 == TCFG_MQTT_PUB_QOS
    network_atcmd_enqueue(app, ATCMD_ID_NB_MQPUB, 0, "OK", "+MQPUBCOMP", 5000, 1000, 1);
    // OK 
    // +MQPUBREC:0,0,6 
    // +MQPUBCOMP:0,0,6 
    #else
    network_atcmd_enqueue(app, ATCMD_ID_NB_MQPUB, 0, "OK", "+MQPUBACK", 5000, 1000, 1);
    #endif
    
    #endif
}

void rtc_sync_cclk_set_atcmd_send(struct app_t* app)
{
    #if TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_4G
        network_atcmd_enqueue(app, ATCMD_ID_4G_CCLK, 0, "OK", "+CCLK", 3000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 0);
    #elif TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_NB
        network_atcmd_enqueue(app, ATCMD_ID_NB_CCLK, 0, "OK", "+CCLK", 3000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 0);
    #endif
}

void network_module_version(struct app_t* app)
{
    #if TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_4G

    #elif TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_NB
        network_atcmd_enqueue(app, ATCMD_ID_NB_CGMR, 0, "OK", "OK", 3000, TCFG_ATCMD_SEND_INTERVAL_MIN_MS, 0);
    #endif
    
}

void network_mqtt_connect_atcion(struct app_t* app)
{
    app->network.net_connecting = 1;
#if TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_4G
    cat1_mqtt_connect_atcmd_send(app);		// 4G 连接MQTT服务
#elif TCFG_NETWORK_MODULE_TYPE == NETWORK_MODULE_NB	
    nbiot_mqtt_connect_atcmd_send(app);	// NB 连接MQTT服务
#endif
}

/**
 * @brief   网络模块AT命令串口中断
*/
void UART4_ISR_Handler (void) interrupt UART4_VECTOR
{
	if(S4RI)
	{
		CLR_RI4();

        #if 1
        // TODO: 收到串口数据更新一次接收计时，数据接收完等待指定时间没收到新数据认为一帧数据接收完成
        jiffes_get(&_this->network.recv_starttime);
        #else
        if (_this->network.rxlen == 0) {
            jiffes_get(&_this->network.recv_starttime);
        }
        #endif

        _this->network.rxbuf[_this->network.rxlen++] = S4BUF;

        if (sizeof(_this->network.rxbuf) == _this->network.rxlen ) {
            _this->network.rxlen = 0;
            memset(_this->network.rxbuf, 0, sizeof(_this->network.rxbuf));
        }
	}

	if(S4TI)
	{
		CLR_TI4();
		
        #if(UART_QUEUE_MODE == 1)   //判断是否使用队列模式
		if(COM4.TX_send != COM4.TX_write)
		{
		 	S4BUF = TX4_Buffer[COM4.TX_send];
			if(++COM4.TX_send >= COM_TX4_Lenth)		COM4.TX_send = 0;
		}
		else	COM4.B_TX_busy = 0;
        #else
        COM4.B_TX_busy = 0;     //使用阻塞方式发送直接清除繁忙标志
        #endif
	}
}
#endif
